import json
import os
import time
from tqdm import tqdm
import shutil
import argparse

from colorama import Back, Style
from py2neo import Graph, Relationship, Node

BLOG_ROOT = "./data/blog"
BLOG_CACHE_ROOT = os.path.join(BLOG_ROOT, "cache")
LOG_CONFIG_FILE = "./config/neo4j.json"
meta_path = os.path.join(BLOG_ROOT, "meta.json")

def get_parser_args():
    parser = argparse.ArgumentParser()
    parser.add_argument('--all_files', action='store_true')
    parser.add_argument('--blog_path', type=str, default=None, help="需要更新到服务器的博客名字，仅限于修改了内容的文章，而不是文章标题、cover等")

    return parser.parse_args()

def update_all_files():
    print(Back.BLUE, "[PUS]", Style.RESET_ALL, "将资源上传到服务器")
    os.system("scp -r data/blog root@101.43.239.71:/usr/local/go/ws/DustBE/data")

def update_one_file(path):
    print('debug {}'.format(path))
    assert os.path.exists(path), f'{path} 不存在！'
    os.system("scp -r \"{}\" root@101.43.239.71:/usr/local/go/ws/DustBE/data/blog".format(path))

# 检查
def check_config():
    if not os.path.exists(LOG_CONFIG_FILE):
        print("Error: Neo4j数据库配置文件{}不存在".format(LOG_CONFIG_FILE))
        exit(-1)
    if not os.path.exists(meta_path):
        print("Error: meta文件不存在，先运行make_blog_meta.py")
        exit(-1)
    if not os.path.exists(BLOG_CACHE_ROOT):
        print("Error: 需要更新的文件夹不存在 {}".format(BLOG_CACHE_ROOT))
        exit(-1)

def default_update():
    with open(meta_path, "r", encoding="utf-8") as fp:
        meta_json = json.load(fp=fp)

    print(Back.GREEN, "[LOG]", Style.RESET_ALL, "更新现存博客...")
    for file in tqdm(os.listdir(BLOG_ROOT)):
        file_path = os.path.join(BLOG_ROOT, file)
        if not os.path.isfile(file_path) or not file.endswith(".md"):
            continue
        lines = []
        for line in open(file_path, "r", encoding="utf-8"):
            lines.append(line.strip())
            if len(lines) == 2:
                break
            
        tags = json.loads(lines[0])
        imgUrl = lines[1]

        tp = os.path.getmtime(file_path)
        adjustTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(tp))

        file_name = file.rstrip(".md")
        index = meta_json["index"][file_name]
        meta_json["blog"][index]["tags"] = tags
        meta_json["blog"][index]["adjustTime"] = adjustTime
        meta_json["blog"][index]["imgUrl"] = imgUrl


    seq = len(meta_json["blog"])
    print(Back.GREEN, "[SUC]", Style.RESET_ALL, "拉取新的博客...")
    for file in os.listdir(BLOG_CACHE_ROOT):
        tp = os.path.getmtime(os.path.join(BLOG_CACHE_ROOT, file))
        adjustTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(tp))
        if file.endswith(".md"):
            file_name = file.rstrip(".md")
            file_path = os.path.join(BLOG_CACHE_ROOT, file)
            lines = []
            for line in open(file_path, "r", encoding="utf-8"):
                lines.append(line.strip())
                if len(lines) == 2:
                    break

            try:
                tags = json.loads(lines[0])
            except:
                print(Back.RED, "[ERR]", Style.RESET_ALL,  "在提取文件「{}」的topic时出错，请检查是否正确书写Topic!".format(file))
                continue
            
            imgUrl = lines[1]

            meta_json["blog"].append({
                "name" : file_name,
                "tags" : tags,
                "adjustTime" : adjustTime,
                "imgUrl" : imgUrl,
                "seq" : seq
            })
            meta_json["index"][file_name] = seq
            seq += 1
            shutil.move(file_path, os.path.join(BLOG_ROOT, file))

    # 在保存在本地前进行对比，确定哪些是需要上传到neo4j数据库的
    print(Back.GREEN, "[SUC]", Style.RESET_ALL, "正在对比元数据...")

    with open(meta_path, "r", encoding="utf-8") as fp:
        pre_meta_json = json.load(fp=fp)

    need_update_blogs = []
    for update_item in meta_json["blog"]:
        if update_item["name"] not in pre_meta_json["index"]:
            need_update_blogs.append(update_item)
            print(Back.BLUE, "[UPD]", Style.RESET_ALL, "发现 {} 需要更新imgUrl或topic".format(update_item["name"]))
            continue
        
        index = pre_meta_json["index"][update_item["name"]]
        item = pre_meta_json["blog"][index]
        
        if set(item["tags"]) != set(update_item["tags"]) or item["imgUrl"] != update_item["imgUrl"]:
            need_update_blogs.append(update_item)
            print(Back.BLUE, "[UPD]", Style.RESET_ALL, "发现 {} 需要更新imgUrl或topic".format(update_item["name"]))
        
    if len(need_update_blogs) > 0:
        print(Back.BLUE, "[PUS]", Style.RESET_ALL, "需要更新的博客数量 {} ，正在上传数据库".format(len(need_update_blogs)))
        # 配置数据库
        with open(LOG_CONFIG_FILE, "r", encoding="utf-8") as fp:
            c = json.load(fp)
        config = {
            "profile" : "http:" + c["url"].split(":")[1] + ":8002",
            "name" : c["name"],
            "password" : c["password"]
        }
        g = Graph(**config)

        # 数据库的关系
        BELONG_TO = Relationship.type("belongTo")

        for blog in tqdm(need_update_blogs):
            blog_node = Node("Blog", name=blog["name"], adjustTime=blog["adjustTime"], seq=blog["seq"], imgUrl=blog["imgUrl"])
            for tags in blog["tags"]:
                topic_node = Node("Topic", name=tags)
                topic_node.__primarylabel__ = "Topic"
                topic_node.__primarykey__ = "name"
                g.merge(BELONG_TO(blog_node, topic_node), "Blog", "name")        

    with open(meta_path, "w", encoding="utf-8") as fp:
        json.dump(obj=meta_json, fp=fp, indent=4, ensure_ascii=False)

    # 更新需要更新的博客
    for blog in need_update_blogs:
        blog_path = os.path.join(BLOG_ROOT, blog['name'] + '.md')
        if not os.path.exists(blog_path):
            print(Back.YELLOW, "WARNING", Style.RESET_ALL,  "没有找到需要更新的文件路径 {}".format(blog_path))
            continue
        update_one_file(blog_path)


if __name__ == "__main__":
    args = get_parser_args()
    blog_path = args.blog_path
    use_all_files = args.all_files
    check_config()

    if blog_path is not None:
        update_one_file(blog_path)
    elif use_all_files:
        update_all_files()
    else:
        default_update()

    print(Back.GREEN, "DONE :D", Style.RESET_ALL)
    print()